package main;

import java.util.Iterator;

import tools.DoubleVector;
import tools.IntVector;
import tools.Vector;
import uncertainty.UncertaintySet;
import util.Memorier;

public class BoundCalculator {
	
	private Memorier mem;
	private Vector<Integer> m;
	private Vector<Double> delta;
	private Vector<Double> g;
	private int n;
	private int i;
	private int j;
	
	private void calcn(UncertaintySet s, int dim){
		n=0;
		Iterator<Vector<Double>> it1 = s.extremePoints();
		while(it1.hasNext()){
			it1.next();
			n++;
			it1.remove();
		}
	}
	
	private void calcm(UncertaintySet s, int dim){
		Vector<Double> e1;
		Vector<Double> e2;
		Iterator<Vector<Double>> it1 = s.extremePoints();
		Iterator<Vector<Double>> it2;
		int[] cont = new int[dim];
		while(it1.hasNext()){
			e1 = it1.next();
			for(int t = 0; t < dim; t++) cont[t] = 0;
			it2 = s.extremePoints();
			while(it2.hasNext()){
				e2 = it2.next();
				for(int l = 0; l < dim; l++)if(e1.isEqual(l, e2)) cont[l]++;
				it2.remove();
			}
			for(int t = 0; t < dim; t++)if(m.get(t) < cont[t]) m.set(t, cont[t]);
			it1.remove();
		}
	}
	
	private void calcdelta(UncertaintySet s, int dim){
		int start;
		int lim = i-j;
		
		Vector<Double> e1;
		Vector<Double> e2;
		Iterator<Vector<Double>> it1 = s.extremePoints();
		Iterator<Vector<Double>> it2;
		double[] cont = new double[dim];
		while(it1.hasNext()){
			e1 = it1.next();
			for(int t = 0; t < dim; t++) cont[t] = 0;
			it2 = s.extremePoints();
			while(it2.hasNext()){
				e2 = it2.next();
				for(int l = 0; l < dim; l++){
					if(l - lim < 0) start = 0;
					else start = l-lim;
					cont[l] = Math.abs(e1.sum(start, l) - e2.sum(start, l));
				}
				it2.remove();
			}
			for(int t = 0; t < dim; t++)if(delta.get(t) < cont[t]) delta.set(t, cont[i]);
			it1.remove();
		}
	}
	
	private void calcg(Vector<Double> h, Vector<Double> p){
		for(int t = 0; t < h.getDim(); t++) g.set(t, h.get(t) > p.get(t)? h.get(t):p.get(t));
	}
	
	public BoundCalculator(int i, int j, Vector<Double> h, Vector<Double> p, UncertaintySet s) {
		this.i = i;
		this.j = j;
		g = new DoubleVector(h.getDim());
		delta = new DoubleVector(h.getDim());
		m = new IntVector(h.getDim());
		calcdelta(s, h.getDim());
		calcg(h, p);
		calcm(s, h.getDim());
		calcn(s, h.getDim());
	}
	
	public double Bound1(){
		double bd = 0;
		
		for(int t = 0; t < m.getDim(); t++){
			bd += g.get(t)*delta.get(t)*(1.0 - 1.0/((double)n));
		}
		
		return bd;
	}

	public double Bound2(){
		double bd = 0;
		
		for(int t = 0; t < m.getDim(); t++){
			
			bd += g.get(t)*delta.get(t)*(1.0 - m.get(t)/(double)n);
		}
		
		return bd;		
	}
	
}
